home *** CD-ROM | disk | FTP | other *** search
- unit UnitMulticaster;
- interface
- uses SysUtils, Classes;
- type
-
- TMethodReference = procedure of object;
- TMethodReferenceList = class(TObject)
- private
- FList: TList;
- protected
- procedure Add(aMethodReference: TMethodReference);
- procedure Remove(aMethodReference: TMethodReference);
- procedure Clear;
- public
- constructor Create;
- destructor Destroy; override;
- procedure RemoveAllForAnObject(anObject: TObject);
- end;
-
- TEvent = class(TObject)
- private
- FSender: TObject;
- public
- constructor Create(aSender: TObject);
- property Sender: TObject read FSender;
- end;
-
- TEventAfterChange = class(TEvent);
-
- TEventListener = procedure(aMulticasterEvent: TEvent) of object;
- TEventMulticaster = class(TMethodReferenceList)
- public
- procedure AddListener(aMulticasterEventListener: TEventListener);
- procedure RemoveListener(aMulticasterEventListener: TEventListener);
- procedure Broadcast(aMulticasterEvent: TEvent);
- end;
-
- implementation
-
- { TEventMulticaster }
-
- procedure TEventMulticaster.AddListener(aMulticasterEventListener: TEventListener);
- begin
- Add(TMethodReference(aMulticasterEventListener));
- end;
-
- procedure TEventMulticaster.Broadcast(aMulticasterEvent: TEvent);
- var i: integer;
- var pMulticasterEventListener: ^TEventListener;
- begin
- try
- for i := 0 to (FList.Count - 1) do
- begin
- pMulticasterEventListener := FList.Items[i];
- pMulticasterEventListener^(aMulticasterEvent);
- end;
- finally
- aMulticasterEvent.Free;
- end; // try..finally
- end;
-
- procedure TEventMulticaster.RemoveListener(aMulticasterEventListener: TEventListener);
- begin
- Remove(TMethodReference(aMulticasterEventListener));
- end;
-
- { TMethodReferenceList }
-
- procedure TMethodReferenceList.Add(aMethodReference: TMethodReference);
- var pMethodReference: ^TMethodReference;
- var i: integer;
- begin
- // Look at each method in the collection to see if aMethodReference has
- // already been added.
- for i := 0 to (FList.Count - 1) do
- begin
- // Put the untyped FList pointer into the typed method reference pointer.
- pMethodReference := FList.Items[i];
- // Don't do anything if the method reference has already been stored.
- if ( TMethod(pMethodReference^).Code = TMethod(aMethodReference).Code )
- and ( TMethod(pMethodReference^).Data = TMethod(aMethodReference).Data )
- then exit;
- end;
- // If we get this far we're adding a new method reference. First allocate
- // space to store the saved reference.
- New(pMethodReference);
- // Now save the method reference data in the new space.
- pMethodReference^ := aMethodReference;
- // Finally, save the address of the method reference data in the TList.
- FList.Add(pMethodReference);
- end;
-
- procedure TMethodReferenceList.Clear;
- var pMethodReference: ^TMethodReference;
- begin
- while (FList.Count > 0) do
- begin
- pMethodReference := FList.Items[0];
- Dispose(pMethodReference);
- FList.Delete(0);
- end;
- end;
-
- constructor TMethodReferenceList.Create;
- begin
- inherited;
- FList := TList.Create;
- end;
-
- destructor TMethodReferenceList.Destroy;
- begin
- Clear;
- FList.Free;
- inherited;
- end;
-
- procedure TMethodReferenceList.Remove(aMethodReference: TMethodReference);
- var pMethodReference: ^TMethodReference;
- var i: integer;
- begin
- // Look at each method in the collection.
- for i := (FList.Count - 1) downto 0 do
- begin
- // Put the untyped FList pointer into the typed method reference pointer.
- pMethodReference := FList.Items[i];
- // If the method reference is found then de-allocate its memory and remove
- // the reference from FList.
- if ( TMethod(pMethodReference^).Code = TMethod(aMethodReference).Code )
- and ( TMethod(pMethodReference^).Data = TMethod(aMethodReference).Data ) then
- begin
- Dispose(pMethodReference);
- FList.Delete(i);
- exit;
- end;
- end;
- end;
-
- procedure TMethodReferenceList.RemoveAllForAnObject(anObject: TObject);
- var pMulticasterEventListener: ^TEventListener;
- var i: integer;
- begin
- // Look at each method in the collection.
- for i := (FList.Count - 1) downto 0 do
- begin
- // Put the untyped FList pointer into the typed method reference pointer.
- pMulticasterEventListener := FList.Items[i];
- // If any procedure or function reference is associated with the passed
- // object then de-allocate its memory and remove the reference from FList.
- if ( TMethod(pMulticasterEventListener^).Data = anObject ) then
- begin
- Dispose(pMulticasterEventListener);
- FList.Delete(i);
- end; // then begin
- end; // do begin
- end;
-
- { TEvent }
-
- constructor TEvent.Create(aSender: TObject);
- begin
- inherited Create;
- FSender := aSender;
- end;
-
- end.
-